/**
 * public中的方法为【对某些数据操作的公共方法】，其他页面引入即可使用
 * 1、操作方法
 * 2、判断方法
 * 3、添加api事例
 */

/****************************************@param {1、以下为操作方法}**************************************************** */
/**
 *拿符号分割对象中的字符串
 * @param {*} arr 数组对象
 * @param {*} name 截取的字段
 * @param {*} symbol 符号
 * @returns
 */
export function handleJoinName(arr, name, symbol) {
    if (!arr || arr.length === 0) {
        return false;
    }
    let result = arr.map((item) => item[name]).join(symbol);
    return result;
}

/**
 *根据传参来对时间格式进行操作
 * @param {*} val 值
 * @param {*} type 格式     yyyy /yyyy-MM /yyyy-MM-dd /yyyy-MM-dd HH /yyyy-MM-dd HH:mm /yyyy-MM-dd HH:mm:ss
 * @returns
 */

export function handleFormatTime(val, type) {
    if (!val) {
        return "-";
    }
    const date = new Date(val);
    const formatter = new Intl.DateTimeFormat("zh-CN", {
        year: "numeric",
        month: "2-digit",
        day: "2-digit",
        hour: "2-digit",
        minute: "2-digit",
        second: "2-digit",
        hour12: false, // 使用24小时制
    });

    // 根据type返回不同的格式化结果
    const formattedDate = formatter.format(date);
    switch (type) {
        case "yyyy":
            return formattedDate.slice(0, 4);
        case "yyyy-MM":
            return formattedDate.slice(0, 7);
        case "yyyy-MM-dd":
            return formattedDate.slice(0, 10);
        case "yyyy-MM-dd HH":
            return formattedDate.slice(0, 13);
        case "yyyy-MM-dd HH:mm":
            return formattedDate.slice(0, 16);
        case "yyyy-MM-dd HH:mm:ss":
            return formattedDate;
        default:
            return formattedDate; // 默认返回完整日期时间
    }
}

/**
 通过文件的后缀判断文件是什么类型
 */

var imgExt = new Array(".png", ".jpg", ".jpeg", ".bmp", ".gif"); //图片文件的后缀名
var videoExt = new Array(
    ".mp4",
    ".m2v",
    ".mkv",
    ".rmvb",
    ".wmv",
    ".avi",
    ".flv",
    ".mov",
    ".m4v"
); //视频文件的后缀名
var radioExt = new Array(".mp3", ".wav", ".wmv"); //音频文件的后缀名
var docExt = new Array(".doc", ".docx"); //word文件的后缀名
var xlsExt = new Array(".xls", ".xlsx"); //excel文件的后缀名
var pptExt = new Array(".ppt", ".pptx"); //ppt文件的后缀名
var txtExt = new Array(".txt"); //txt文件的后缀名
var pdfExt = new Array(".pdf"); //pdf文件的后缀名

//获取文件名后缀名
String.prototype.extension = function () {
    var ext = null;
    var name = this.toLowerCase();
    var i = name.lastIndexOf(".");
    if (i > -1) {
        var ext = name.substring(i);
    }
    return ext;
};

//判断Array中是否包含某个值
Array.prototype.contain = function (obj) {
    for (var i = 0; i < this.length; i++) {
        if (this[i] === obj) return true;
    }
    return false;
};

String.prototype.extMatch = function (extType) {
    if (extType.contain(this.extension())) return true;
    else return false;
};

/**
 *判断当前的文件是什么类型的文件
 * @param {*} val 文件后缀
 * @returns
 */

export function handleFileSuffix(val) {
    if (!val) {
        return false;
    }
    if (val.extMatch(imgExt)) {
        return "image";
    } else if (val.extMatch(videoExt)) {
        return "video";
    } else if (val.extMatch(radioExt)) {
        return "radio";
    } else if (val.extMatch(docExt)) {
        return "word";
    } else if (val.extMatch(xlsExt)) {
        return "excel";
    } else if (val.extMatch(pptExt)) {
        return "ppt";
    } else if (val.extMatch(txtExt)) {
        return "txt";
    } else if (val.extMatch(pdfExt)) {
        return "pdf";
    }
}

/**
 * 下载流文件
 * @param {*} val 后端返回的流
 * @param {*} name  下载文件的名称
 */

export function handleDownloadBlodFiles(data, name, suffix) {
    let blob = new Blob([data]);
    let url = window.URL.createObjectURL(blob);
    let a = document.createElement("a");
    a.href = url;
    a.download = name;
    a.click();
    // 释放这个临时的对象url
    window.URL.revokeObjectURL(url);
}

/**
 * 判断浏览器类型和版本
 * @returns
 */
export function handleBrowserType() {
    var userAgent = navigator.userAgent.toLowerCase();
    var testCenter = {
        ie: function isIE() {
            //ie?
            if (!!window.ActiveXObject || "ActiveXObject" in window)
                return true;
            else return false;
        },
        edge: () => {
            return /dge/.test(userAgent);
        },
        chrome: () => {
            return /chrome/.test(userAgent);
        },
        safari: () => {
            return /safari/.test(userAgent) && !/chrome/.test(userAgent);
        },
        opera: () => {
            return /opera/.test(userAgent);
        },
        msie: () => {
            return /msie/.test(userAgent) && !/opera/.test(userAgent);
        },
        mozilla: () => {
            return (
                /mozilla/.test(userAgent) &&
                !/(compatible|webkit)/.test(userAgent)
            );
        },
    };
    var browserObj = {};
    for (var k in testCenter) {
        var result = testCenter[k]();
        var version = (userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) ||
            [])[1];
        if (result) {
            browserObj.browser = k;
            browserObj.version = version;
            return browserObj;
        }
    }
}

/**
 * 生成随机数
 * @param {*} len
 * @returns
 */
export function handleRandomUid(len) {
    len = len || 6;
    len = parseInt(len, 10);
    len = isNaN(len) ? 6 : len;
    const seed =
        "0123456789abcdefghijklmnopqrstubwxyzABCEDFGHIJKLMNOPQRSTUVWXYZ";
    const seedLen = seed.length - 1;
    let uuid = "";
    while (len--) {
        uuid += seed[Math.round(Math.random() * seedLen)];
    }
    return uuid;
}

/**
 * 保留任意位小数
 * @param {*} num 实际数字
 * @param {*} decimal 保留位数
 */
export function handleKeepAnyDecimal(num, decimal = 2) {
    const level = Math.pow(10, decimal);
    var result = parseFloat(num);
    if (isNaN(result)) {
        return "";
    }
    result = Math.round(num * level) / level;
    return result;
}

/**
 * // 判断两个对象的值是否相等  true相等 false不等  仅能判断一层
 * @param {*} obj1
 * @param {*} obj2
 * @returns
 */
export function handleDiffObject(obj1, obj2) {
    const keys1 = Object.keys(obj1);
    const keys2 = Object.keys(obj2);
    if (keys1.length !== keys2.length) {
        // //
        return false;
    } else {
        for (const key in obj1) {
            if (!obj2.hasOwnProperty(key)) {
                return false;
            }
            // 类型相同
            if (typeof obj1[key] === typeof obj2[key]) {
                // 同为引用类型
                if (
                    typeof obj1[key] === "object" &&
                    typeof obj2[key] === "object"
                ) {
                    if (obj1[key] !== null && obj2[key] !== null) {
                        const equal = diffObject(obj1[key], obj2[key]);
                        if (!equal) {
                            return false;
                        }
                    }
                }
                // 同为基础数据类型
                if (
                    typeof obj1[key] !== "object" &&
                    typeof obj2[key] !== "object" &&
                    obj1[key] !== obj2[key]
                ) {
                    return false;
                }
            } else {
                if (
                    (obj1[key] === null && obj2[key] === undefined) ||
                    (obj2[key] === null && obj1[key] === undefined)
                ) {
                    // 如果值为null和undefind则认为是相等的
                    return true;
                }
                return false;
            }
        }
    }
    return true;
}

/**
 * 将对象转为数组[{code: '', value: []}] 结构
 * @param {*} obj
 * @returns
 */
export function handleObjTransArray(obj) {
    const arr = [];
    if (typeof obj !== "object") {
        return false;
    } else {
        for (const [key, value] of Object.entries(obj)) {
            arr.push({ value: key, lable: value });
        }
        return arr;
    }
}

/**
 * 将数字按千分位显示，小数点后的不做千分位显示，保留原数字小数位
 * @param {number | string} num 初始数字
 * @returns string
 */
export function handleThousandBitSeparator(num) {
    const str = num.toString();
    const arr = str.split(".");
    const str1 = arr[0].replace(/\d{1,3}(?=(\d{3})+$)/g, function (a, b, c) {
        return a + ",";
    });
    return arr[1] ? str1 + "." + arr[1] : str1;
}

/**
 * 固定保留小数点后几位并不进行四舍五入
 * @param {*} number 
 * @param {*} digits 
 * @returns 
 */
export function handleToFixedNoRound(number, digits,isCovering) {
    // 将数字转换为字符串并分割为整数部分和小数部分
    const parts = number.toString().split('.');
    // 确保小数部分不超过指定的位数
    const decimalPart = parts[1] ? parts[1].substring(0, digits) : '00';
    // 组合整数部分和小数部分，不进行四舍五入
    const result = parts[0] + '.' + decimalPart;
    return parseFloat(result);
  }

/****************************************@param {2、以下为判断方法}**************************************************** */

/**
 * 判断对象是否为空 true为空 false不为空
 * @param {*} obj
 */
export function isEmpty(obj) {
    for (let key in obj) {
        return false;
    }
    return true;
}

/**
 * //判断数据源是不是json数据
 * @param {*} str
 * @returns
 */
export function isJson(str) {
    try {
        if (typeof JSON.parse(str) == "object") {
            return true;
        }
    } catch (e) {
        console.log("e", e);
    }
    return false;
}

/****************************************3、以下为添加api的使用方法************************************** */

/**
 * @param  单独添加全局api  需要在main.js中引入注册
 */
// import { handleJoinName } from "@/utils/public";
// app.config.globalProperties.$handleJoinName = handleJoinName;
// .vue中使用
// this.$handleJoinName(this.list,'name','+')

/**
 * @param   一次性将方法全部添加为全局api
 * */
// export default {
//     install(app) {
//         // 定义全局方法
//         const globalMethods = {
//             handleJoinName: handleJoinName,
//             // 可以继续添加更多的方法
//         };

//         // 将全局方法添加到 app 的属性中
//         Object.keys(globalMethods).forEach((methodName) => {
//             app.config.globalProperties[`$${methodName}`] =
//                 globalMethods[methodName];
//         });
//     },
// };
// .vue中使用
// this.$handleJoinName(this.list,'name','+')

/**
 *@param {全局API的优缺点}
 *@param {优点：}
 *
 *易于访问：全局API可以在任何组件中直接使用，无需重复导入。
 *统一管理：集中管理所有API，便于维护和更新。
 *减少冗余：避免在多个组件中重复编写相同的逻辑。
 *@param {缺点：}
 *
 *全局状态污染：过度使用全局API可能导致全局命名空间的污染。
 *依赖问题：组件可能过度依赖全局状态，使得组件之间的耦合度增加。
 *性能问题：如果全局API包含大量方法，即使组件未使用所有方法，也可能影响打包体积和初始化性能。
 *
 *@param {单独引入使用的优缺点}
 *@param {优点：}
 *
 *按需加载：只加载组件需要的方法，可以减少不必要的代码加载。
 *模块化：促进代码的模块化，每个组件只关注自己需要的API。
 *灵活性：可以更灵活地替换或修改特定API，而不会影响到其他组件。
 *@param {缺点：}
 *
 *导入冗余：在多个组件中重复导入相同的方法，导致代码冗余。
 *维护难度：如果API分散在不同文件中，可能难以追踪和管理。
 *潜在的命名冲突：在大型项目中，不同组件可能使用相同名称的方法，导致潜在的命名冲突。
 *
 *@param {实践建议：}
 *对于通用性高、使用频率大的公共方法，可以考虑添加为全局API。
 *对于特定场景或特定组件的私有方法，建议单独引入使用。
 *使用模块化的组织方式，如将相关API组织在同一个文件或模块中，便于管理和维护。
 *考虑使用代码分割和懒加载技术，以优化性能和加载时间。
 */
